package com.zxx.flowerstore.utils.utils;

import com.zxx.flowerstore.entity.enums.ResultEnum;
import com.zxx.flowerstore.utils.common.BaseEntity;
import com.zxx.flowerstore.utils.common.MyException;
import com.zxx.flowerstore.utils.common.RegexConstant;
import com.zxx.flowerstore.utils.common.ThrowingFunction;
import org.apache.commons.lang3.StringUtils;

import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.util.List;
import java.util.Objects;

/**
 * @ClassName DecimalUtil
 * @Author Admin
 * @Date 2021/3/20 11:44
 * @Description DecimalUtil
 * @Version 1.0
 */
public class DecimalUtil {
    public static final String ZERO = BigDecimal.ZERO.toString();

    private static final String GETTER_PREFIX = "get";

    private DecimalUtil() {
    }

    /**
     * 判断是否是数字
     *
     * @param str
     * @return
     */
    public static boolean isNumeric(String str) {
        if (StringUtils.isBlank(str)) {
            return false;
        }
        return str.matches(RegexConstant.UNSIGNED_NUMERIC);
    }

    /**
     * 判断是否是数字
     *
     * @param str
     * @return: boolean
     * @author: zhengxin
     * @date: 2020/5/25 10:29
     * @version: 1.0
     */
    public static boolean isSignedNumeric(String str) {
        if (StringUtils.isBlank(str)) {
            return false;
        }
        return str.matches(RegexConstant.SIGNED_NUMERIC);
    }

    /**
     * 判断是否是整数
     *
     * @param str
     * @return boolean
     * @author zhengxin
     * @date 2020/9/17 11:34
     * @version: 1.0
     */
    public static boolean isInteger(String str) {
        if (StringUtils.isBlank(str)) {
            return false;
        }
        return str.matches(RegexConstant.UNSIGNED_INT);
    }

    /**
     * 判断是否是数字或者空或者空串
     *
     * @param str
     * @return
     */
    public static boolean isBlankOrNumeric(String str) {
        if (StringUtils.isBlank(str)) {
            return true;
        }
        return str.matches(RegexConstant.UNSIGNED_NUMERIC);
    }

    /**
     * 加法
     *
     * @param augend
     * @param addend
     * @return
     */
    public static String add(String augend, String addend) {
        return toDecimal(augend).add(toDecimal(addend)).toString();
    }


    /**
     * 比较
     *
     * @param val1
     * @param val2
     * @return val1-val2
     */
    public static int compareTo(String val1, String val2) {
        return toDecimal(val1).compareTo(toDecimal(val2));
    }

    /**
     * 减法
     *
     * @param subtracted
     * @param subtraction
     * @return
     */
    public static String subtract(String subtracted, String subtraction) {
        return subtractDecimal(subtracted, subtraction).toString();
    }

    /**
     * 减法
     *
     * @param subtracted
     * @param subtraction
     * @return
     */
    public static BigDecimal subtractDecimal(String subtracted, String subtraction) {
        return toDecimal(subtracted).subtract(toDecimal(subtraction));
    }

    /**
     * 除法
     *
     * @param dividend
     * @param divisor
     * @return 默认保留6位小数
     */
    public static String divide(String dividend, String divisor) {
        return divide(dividend, divisor, 6);
    }

    /**
     * 除法
     *
     * @param dividend 被除数
     * @param divisor  除数
     * @param scale    小数点位数
     * @return
     */
    public static String divide(String dividend, String divisor, int scale) {
        if (StringUtils.isBlank(divisor)) {
            return ZERO;
        }
        return divideDecimal(dividend, divisor, scale).toString();
    }

    /**
     * 除法
     *
     * @param dividend
     * @param divisor
     * @return 默认保留6位小数
     */
    public static BigDecimal divideDecimal(String dividend, String divisor) {
        return divideDecimal(dividend, divisor, 6);
    }

    /**
     * 除法
     *
     * @param dividend 被除数
     * @param divisor  除数
     * @param scale    小数点位数
     * @return
     */
    public static BigDecimal divideDecimal(String dividend, String divisor, int scale) {
        if (StringUtils.isBlank(divisor)) {
            return BigDecimal.ZERO;
        }
        return toDecimal(dividend).divide(toDecimal(divisor), scale, BigDecimal.ROUND_HALF_UP);
    }


    /**
     * 乘法
     *
     * @param multiplicand 被乘数
     * @param multiplier   乘数
     * @return
     */
    public static String multiply(String multiplicand, String multiplier) {
        return multiplyDecimal(multiplicand, multiplier).toString();
    }

    /**
     * 乘法
     *
     * @param multiplicand 被乘数
     * @param multiplier   乘数
     * @return
     */
    public static BigDecimal multiplyDecimal(String multiplicand, String multiplier) {
        return toDecimal(multiplicand).multiply(toDecimal(multiplier));
    }


    /**
     * 取相反数
     *
     * @param val
     * @return
     */
    public static String negate(String val) {
        return toDecimal(val).negate().toString();
    }

    /**
     * 字符串转BigDecimal
     * 空或者空串返回0
     *
     * @param val
     * @return
     */
    public static BigDecimal toDecimal(String val) {
        if (StringUtils.isBlank(val)) {
            return BigDecimal.ZERO;
        }
        return new BigDecimal(val);
    }

    /**
     * 转为BigDecimal
     *
     * @param obj
     * @return: java.math.BigDecimal
     * @author: zhengxin
     * @date: 2020/7/14 11:07
     * @version: 1.0
     */
    public static BigDecimal toDecimal(Object obj) {
        if (Objects.isNull(obj)) {
            return BigDecimal.ZERO;
        }
        if (obj instanceof BigDecimal) {
            return (BigDecimal) obj;
        }
        return toDecimal(obj.toString());
    }


    /**
     * 求和
     *
     * @param list
     * @param clazz
     * @param fieldName
     * @return
     * @deprecated as of 2020/7/14, in favor of {@link ListUtils#summing(List, java.util.function.Function)}
     */
    @Deprecated
    public static BigDecimal sumByField(List<? extends BaseEntity> list, Class<? extends BaseEntity> clazz, String fieldName) {
        return sumByMethod(list, clazz, field2Getter(fieldName));
    }

    /**
     * 根据属性名获取get方法名
     *
     * @param fieldName
     * @return
     */
    @Deprecated
    public static String field2Getter(String fieldName) {
        return GETTER_PREFIX + fieldName.substring(0, 1).toUpperCase().concat(fieldName.substring(1));
    }

    /**
     * 求和
     *
     * @param list
     * @param clazz
     * @param methodName
     * @return
     * @deprecated as of 2020/7/14, in favor of {@link ListUtils#summing(List, java.util.function.Function)}
     */
    @Deprecated
    public static BigDecimal sumByMethod(List<? extends BaseEntity> list, Class<? extends BaseEntity> clazz, String methodName) {
        Method method = getMethod(clazz, methodName);
        return list.stream()
                .map(ThrowingFunction.wrapper(item -> (String) method.invoke(item), "程序错误!DecimalUtil->反射调用方法失败："))
                .map(item -> toDecimal(item))
                .reduce(BigDecimal.ZERO, BigDecimal::add);
    }

    /**
     * 根据方法名，通过反射获取方法
     *
     * @param methodName
     * @return
     */
    private static Method getMethod(Class<? extends BaseEntity> clazz, String methodName) {
        try {
            Method method = clazz.getDeclaredMethod(methodName);
            return method;
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
            throw new MyException(ResultEnum.CODE_ERROR.getCode(), "程序错误!DecimalUtil->反射获取方法失败(" + methodName + ")：" + e.getMessage());
        }
    }



    public static BigDecimal nullAsZero(String num) {
//        if (null == num || num == "") {
//            return BigDecimal.ZERO;
//        } else {
//            return new BigDecimal(num);
//        }
        if (StringUtils.isBlank(num)) {
            return BigDecimal.ZERO;
        } else {
            return new BigDecimal(num);
        }


    }

    public static BigDecimal nullAsZero(BigDecimal num) {
        if (null == num) {
            return BigDecimal.ZERO;
        } else {
            return num;
        }
    }

    /**
     * 将百分数转换为小数 -- 9%->9.00
     *
     * @param numberParent
     * @return
     */
    public static String parentNumParseToDecimal(String numberParent) {
        try {
            DecimalFormat df2 = new DecimalFormat("#.00");
            return df2.format(new BigDecimal(numberParent).multiply(new BigDecimal("100")));
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 小数去除零
     *
     * @param val
     * @return: java.lang.String
     * @author: zhengxin
     * @date: 2020/3/11 11:25
     * @version: 1.0
     */
    public static String stripTrailingZeros(String val) {
        return toDecimal(val).stripTrailingZeros().toPlainString();
    }


    /**
     * 保留固定位数小数<br>
     * 采用四舍五入策略 {@link RoundingMode#HALF_UP}<br>
     * 例如保留2位小数：123.456789 =》 123.46
     *
     * @param numberStr 数字值的字符串表现形式
     * @param scale     保留小数位数
     * @return 新值
     */
    public static String round(String numberStr, int scale) {
        BigDecimal value = new BigDecimal(numberStr);
        return value.setScale(scale, RoundingMode.HALF_UP).toString();
    }

}
